/*
 *Copyright (c) [2019-2020]  C2comm, Inc.  All rights reserved.
 *
 *This program is free software; you can redistribute it and/or
 *modify it under the terms of the GNU General Public License
 *as published by the Free Software Foundation; either version 2
 *of the License, or (at your option) any later version.
 *
 *This program is distributed in the hope that it will be useful,
 *but WITHOUT ANY WARRANTY; without even the implied warranty of
 *MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *GNU General Public License for more details.
 *
 *You should have received a copy of the GNU General Public License
 *along with this program; If not, see <https://www.gnu.org/licenses/>
 */
/*
 *Vendor: C2comm
 *Version: 1.0
 *Filename: PCFDispatch.v
 *Target Device: Altera
 *Author : sunxiaotian@c2comm.cn
*/

`timescale 1ns/1ps

module PCFDispatch(
    input wire SYS2CORE_clk,
	input wire SYS2CORE_rst_n,
	
	input wire [37:0] CONF2CORE_sys_conf,
    input wire [27:0] CONF2CORE_dbg_conf,
	input wire [47:0] DC2CORE_device_clk,
	//input from LCP
	input wire [19:0] CORE2SYS_local_clk,
	//input from OPPM
	input wire OPPM2PDM_pcf_tx_cb_wr,
	input wire [63:0] OPPM2PDM_pcf_tx_cb,
	output wire OPPM2PDM_pcf_tx_cb_ready,
	
	//output to PCF_TX
	output reg CORE2PT_pcf_tx_des_wr,
	output reg [131:0] CORE2PT_pcf_tx_des,
	input wire PT2CORE_pcf_tx_des_ready
    );


reg PCF2OC_pcf_rx_cb_rd;
reg [63:0] cur_pcf_cb_rd;
wire [63:0] PCF2OC_pcf_rx_cb_rdata;
wire full;
wire PCF2OC_pcf_rx_cb_empty;
wire [5:0] data_count;

localparam IDLE_S = 2'b01,
		WAIT_S = 2'b10;
		
reg [1:0] state;	
	
assign OPPM2PDM_pcf_tx_cb_ready = !full;

always @(posedge SYS2CORE_clk or negedge SYS2CORE_rst_n) begin
	if(!SYS2CORE_rst_n) begin
		PCF2OC_pcf_rx_cb_rd <= 1'b0;
		CORE2PT_pcf_tx_des <= 132'b0;
		cur_pcf_cb_rd <= 64'b0;
		CORE2PT_pcf_tx_des_wr <= 1'b0;
		PCF2OC_pcf_rx_cb_rd <= 1'b0;
		state <= IDLE_S;
	end
	else begin
		case(state) 
			IDLE_S: begin
				if(!PCF2OC_pcf_rx_cb_empty) begin
					PCF2OC_pcf_rx_cb_rd <= 1'b1;
					cur_pcf_cb_rd <= PCF2OC_pcf_rx_cb_rdata;
					CORE2PT_pcf_tx_des_wr <= 1'b0;
					state <= WAIT_S;
				end
				else begin
				    CORE2PT_pcf_tx_des_wr <= 1'b0;
					cur_pcf_cb_rd <= 36'b0;
					state <= IDLE_S;
				end
			end
			WAIT_S: begin
				if( PT2CORE_pcf_tx_des_ready == 1'b1) begin
					CORE2PT_pcf_tx_des[47:0] <= cur_pcf_cb_rd[63:16];
					CORE2PT_pcf_tx_des[59:52] <= CONF2CORE_sys_conf[29:22]; 
					CORE2PT_pcf_tx_des[67:60] <= CONF2CORE_sys_conf[37:30]; 
					CORE2PT_pcf_tx_des[99:68] <= cur_pcf_cb_rd[13:6];
					CORE2PT_pcf_tx_des[131:100] <= cur_pcf_cb_rd[5:0];
					if(cur_pcf_cb_rd[15:14] == 2'b00) begin CORE2PT_pcf_tx_des[51:48] <= 4'h4; end//CS
					else if(cur_pcf_cb_rd[15:14] == 2'b01) begin CORE2PT_pcf_tx_des[51:48] <= 4'h8;end//CA
					else if(cur_pcf_cb_rd[15:14] == 2'b10)  begin CORE2PT_pcf_tx_des[51:48] <= 4'h2;end//IN
					
					CORE2PT_pcf_tx_des_wr <= CONF2CORE_dbg_conf[27];
					PCF2OC_pcf_rx_cb_rd <= 1'b0;
					state <= IDLE_S;
				end
				else begin
					PCF2OC_pcf_rx_cb_rd <= 1'b0;
					CORE2PT_pcf_tx_des_wr <= 1'b0;
					state <= WAIT_S;
				end
			end
			default: begin
				PCF2OC_pcf_rx_cb_rd <= 1'b0;
				CORE2PT_pcf_tx_des <= 132'b0;
				cur_pcf_cb_rd <= 64'b0;
				CORE2PT_pcf_tx_des_wr <= 1'b0;
				state <= IDLE_S;
			end
		endcase
	end
end

pcf_cb_fifo pcf_cb_fifo_inst(
.clock(SYS2CORE_clk),
.data(OPPM2PDM_pcf_tx_cb),
.wrreq(OPPM2PDM_pcf_tx_cb_wr & CONF2CORE_dbg_conf[27]),
.rdreq(PCF2OC_pcf_rx_cb_rd),
.q(PCF2OC_pcf_rx_cb_rdata),
.full(full),
.empty(PCF2OC_pcf_rx_cb_empty),
.usedw(data_count)
);
	
endmodule
